package com.okcoin.rest;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JsonConfig;
import net.sf.json.util.NewBeanInstanceStrategy;

import org.apache.http.HttpException;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chiyou.common.indicator.DMI;
import com.chiyou.common.indicator.KDJ;
import com.chiyou.common.indicator.KLineData;
import com.chiyou.common.models.HisData;
import com.chiyou.common.utils.PropertiesUtil;
import com.chiyou.common.utils.PropertiesUtils;
import com.chiyou.common.utils.RedisUtilStr;
import com.chiyou.common.utils.RedisUtils;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.okcoin.rest.future.IFutureRestApi;
import com.okcoin.rest.future.impl.FutureRestApiV1;
import com.okcoin.rest.future.models.Btc;
import com.okcoin.rest.future.models.Contracts;
import com.okcoin.rest.future.models.Holding;
import com.okcoin.rest.future.models.Info;
import com.okcoin.rest.future.models.Ltc;
import com.okcoin.rest.future.models.OkCoinUserInfo;
import com.okcoin.rest.future.models.OkcoinOrder;
import com.okcoin.rest.future.models.Orders;
import com.okcoin.rest.future.models.Position;
import com.okcoin.rest.future.models.Trade;

/**
 * 期货 REST API 客户端请求
 * 
 * @author zhangchi
 *
 */
public class FutureClient {
	public static void main(String[] args) throws HttpException, IOException, NumberFormatException, ParseException {

		String api_key = PropertiesUtils.getInstance(System.getProperty("user.dir") + "/conf/conf.properties").getProperty("apikey");
		String secret_key = PropertiesUtils.getInstance(System.getProperty("user.dir") + "/conf/conf.properties").getProperty("secretkey");
		String url_prex = PropertiesUtils.getInstance(System.getProperty("user.dir") + "/conf/conf.properties").getProperty("urlprex");
		System.out.println(System.getProperty("user.dir") + "\\conf\\conf.properties");
		System.out.println(api_key);

		//
		// String current_tard_price =
		// PropertiesUtils.getInstance(System.getProperty("user.dir") +
		// "/conf/conf.properties").getProperty("current_tard_price");
		// String option_status =
		// PropertiesUtils.getInstance(System.getProperty("user.dir") +
		// "/conf/conf.properties").getProperty("option_status");
		// String current_order_id =
		// PropertiesUtils.getInstance(System.getProperty("user.dir") +
		// "/conf/conf.properties").getProperty("current_order_id");
		// String netwok_val =
		// PropertiesUtils.getInstance(System.getProperty("user.dir") +
		// "/conf/conf.properties").getProperty("netwok_val");
		// String tard_type =
		// PropertiesUtils.getInstance(System.getProperty("user.dir") +
		// "/conf/conf.properties").getProperty("tard_type");
		// RedisUtilStr redisUtilStr = new RedisUtilStr();
		// redisUtilStr.set("netwok_val", netwok_val,0);
		// redisUtilStr.set("current_tard_price", current_tard_price,0);
		// redisUtilStr.set("option_status", option_status,0);
		// redisUtilStr.set("current_order_id", current_order_id,0);
		// redisUtilStr.set("tard_type", tard_type,0);

		// redisUtilStr.set("api_key", api_key,0);
		// System.out.println("redis:" + redisUtilStr.get(tard_type));
		/**
		 * get请求无需发送身份认证,通常用于获取行情，市场深度等公共信息
		 */
		IFutureRestApi futureGetV1 = new FutureRestApiV1(url_prex);

		/**
		 * post请求需发送身份认证，获取用户个人相关信息时，需要指定api_key,与secret_key并与参数进行签名，
		 * 此处对构造方法传入api_key与secret_key,在请求用户相关方法时则无需再传入，
		 * 发送post请求之前，程序会做自动加密，生成签名。
		 * 
		 */
		IFutureRestApi futurePostV1 = new FutureRestApiV1(url_prex, api_key, secret_key);

		// // 期货行情信息
		// String str5 = futureGetV1.future_ticker("btc_usd", "quarter");
		// System.out.println(str5);
		// // 期货指数信息
		// String str4 = futureGetV1.future_index("btc_usd");
		// System.out.println(str4);
		// // 期货交易信息
		// String str3 = futureGetV1.future_trades("btc_usd", "quarter");
		// System.out.println(str3);
		// // 期货市场深度
		// String str2 = futureGetV1.future_depth("btc_usd", "quarter");
		// System.out.println(str2);
		//
		// String kline = futureGetV1.future_kline("btc_usd", "quarter", "1day",
		// 0, 0);
		// List list = JSONArrayToKLineData(kline);
		//
		// System.out.println("kline:" + kline);
		// // 美元-人民币汇率
		// String str = futureGetV1.exchange_rate();
		// System.out.println(str);

		// 期货下单
		// String tradeResultV1 =
		// futurePostV1.future_trade("btc_usd","this_week", "10.134", "1", "1",
		// "0");
		// JSONObject tradeJSV1 = JSONObject.parseObject(tradeResultV1);
		// String tradeOrderV1 = tradeJSV1.getString("order_id");
		// System.out.println(tradeResultV1);

		// //期货用户订单查询
		// futurePostV1.future_order_info("btc_usd", "this_week",tradeOrderV1,
		// "1", "1", "2");
		//
		// //取消订单
		// futurePostV1.future_cancel("btc_usd", "this_week",tradeOrderV1);

		// 期货账户信息

		// OkCoinUserInfo okCoinUserInfo =
		// JSONObject.toJavaObject(JSONObject.parseArray(userInfo),
		// OkCoinUserInfo.class);

		// System.out.println(okCoinUserInfo.getInfo().getBtc().getBalance());
		// 逐仓期货账户信息

		// System.out.println("userInfo4fix:" +
		// getOkCoinUserInfo(futurePostV1).getInfo().getBtc().getBalance());

		// String tickers = futureGetV1.future_ticker("btc_usd", "quarter");
		
		String kline = futureGetV1.future_kline("btc_usd", "quarter", "1day", 0, 0);
		List<KLineData> kLineDatas = JSONArrayToKLineData(kline);
		KDJ kdj = new KDJ();
		DMI dmi = new DMI();

		kdj.setM_kDatas(KLineDataToHisData(kLineDatas));
		kdj.Calculate();
		dmi.setM_kDatas(KLineDataToHisData(kLineDatas));
		dmi.Calculate();
//		kdj.isBuyOrSell();
		dmi.isBuyOrSell();
		//
		// if (kdj.isBuyOrSell() == 1 && dmi.isBuyOrSell() == 1) {
		// System.out.println("开始做多");
		// }
		//
		 
		// if (kdj.isBuyOrSell() == -1 && dmi.isBuyOrSell() == -1) {
		// System.out.println("开始做空");
		// }

		// if (RedisUtils.getObject("tard_type").equals("0") ||
		// RedisUtils.getObject("tard_type").equals("1")) {
		// OkcoinOrder order = getOrder(futurePostV1, "-1", "2", "1", "50");
		// List<Orders> orderList = order.getOrders();
		//
		// if(orderList.size()>0){
		// Orders obj = orderList.get(0);
		// RedisUtils.addObject("current_tard_price", obj.getPrice());
		// RedisUtils.addObject("current_tard_price", obj.getOrder_id());
		// }
		// }
		//
		// OkcoinOrder okcoinOrder = getOrder(futurePostV1);
		//
		// if (okcoinOrder.getOrders().size() > 0) {
		//
		// RedisUtils.addObject("option_status", 0);
		// List<Orders> orderList = okcoinOrder.getOrders();
		// for (int i = 0; i < orderList.size(); i++) {
		// Orders order = orderList.get(i);
		// System.out.println((System.currentTimeMillis() -
		// Long.parseLong(order.getCreate_date())) / 1000 / 60);
		// if ((System.currentTimeMillis() -
		// Long.parseLong(order.getCreate_date())) / 1000 / 60 > 5) {
		// System.out.println(order.getOrder_id());
		// futurePostV1.future_cancel("btc_usd", "quarter",
		// order.getOrder_id());
		// }
		//
		// }
		//
		// }

		// System.out.println(okcoinOrder.getOrders().get(0).getCreate_date());
		// if (okcoinOrder.getOrders().size() > 0) {
		// RedisUtils.addObject("option_status", 0);
		// }
		// System.out.println(RedisUtils.getObject("option_status"));

		//
		//
		// String trades = futureGetV1.future_trades("btc_usd", "quarter");
		//
		//
		// List<Trade> tradeList =
		// net.sf.json.JSONArray.toList(net.sf.json.JSONArray.fromObject(trades),
		// Trade.class);
		// double newBuy = 0.0F;
		// double newSell = 0.0F;
		// for (int i = 0; i < tradeList.size(); i++) {
		// Trade trade = tradeList.get(i);
		// if (trade.getType().equals("buy")) {
		// newBuy = trade.getPrice();
		//
		// }
		//
		// if (trade.getType().equals("sell")) {
		// newSell = trade.getPrice();
		//
		// }
		//
		// if (newBuy != 0 && newSell != 0)
		// break;
		// }
		// System.out.println("newBuy:" + (newBuy / 100.0));
		// System.out.println("newSell:" + newSell);
		// // 期货用户持仓查询
		// OkCoinUserInfo okCoinUserInfo = getOkCoinUserInfo(futurePostV1);
		// double rights = okCoinUserInfo.getInfo().getBtc().getRights();
		// System.out.println((rights)); ;
		// System.out.println(okCoinUserInfo.getInfo().getBtc().getBalance()); ;
		// System.out.println((7000*0.01)+ " "+(7000*0.0003)); ;
		// System.out.println((okCoinUserInfo.getInfo().getBtc().getRights() *
		// 0.1));
	}

	private static Position getPosition(IFutureRestApi futurePostV1) throws HttpException, IOException {
		String position = futurePostV1.future_position("btc_usd", "quarter");
		System.out.println("position:" + position);
		// 期货用户逐仓持仓查询
		String position4fix = futurePostV1.future_position_4fix("btc_usd", "quarter");
		System.out.println(position4fix);

		Position positionObj = new Position();
		if (JSONObject.parseObject(position).getLong("error_code") == 20022) {
			if (net.sf.json.JSONObject.fromObject(position4fix).getJSONArray("holding").size() > 0) {
				List<Holding> holdings = (List<Holding>) net.sf.json.JSONArray.toList(net.sf.json.JSONObject.fromObject(position4fix).getJSONArray("holding"), Holding.class);
				positionObj.setHolding(holdings);
			} else {
				positionObj.setHolding(new ArrayList<Holding>());
			}
			positionObj.setResult(net.sf.json.JSONObject.fromObject(position4fix).getBoolean("result"));
		} else {
			if (net.sf.json.JSONObject.fromObject(position4fix).getJSONArray("holding").size() > 0) {
				List<Holding> holdings = (List<Holding>) net.sf.json.JSONArray.toList(net.sf.json.JSONObject.fromObject(position).getJSONArray("holding"), Holding.class);
				positionObj.setHolding(holdings);
			} else {
				positionObj.setHolding(new ArrayList<Holding>());
			}
			positionObj.setResult(net.sf.json.JSONObject.fromObject(position).getBoolean("result"));
		}
		return positionObj;
	}

	private static List<KLineData> JSONArrayToKLineData(String klineJosn) {

		System.out.println(klineJosn);
		JSONArray klineArray = JSONArray.parseArray(klineJosn);
		List<KLineData> klines = new ArrayList<KLineData>();
		for (Object obj : klineArray) {
			JSONArray row = (JSONArray) obj;
			KLineData kline = new KLineData();
			kline.setDate(row.getLong(0));
			kline.setOpenPrice(row.getFloatValue(1));
			kline.setHighPrice(row.getFloatValue(2));
			kline.setLowPrice(row.getFloatValue(3));
			kline.setClosePrice(row.getFloatValue(4));
			kline.setTotalAmount(row.getLong(5));
			klines.add(kline);
		}
		return klines;
	}

	private static List<HisData> KLineDataToHisData(List<KLineData> klines) {

		List<HisData> hisDatas = new ArrayList<HisData>();
		for (KLineData obj : klines) {
			HisData hisData = new HisData();
			hisData.setOPEN(obj.getOpenPrice());
			hisData.setCLOSE(obj.getClosePrice());
			hisData.setHIGH(obj.getHighPrice());
			hisData.setLOW(obj.getLowPrice());
			hisData.setTIME(new Date(obj.getDate()));
			hisDatas.add(hisData);
		}

		return hisDatas;
	}

	private static OkCoinUserInfo getOkCoinUserInfo(IFutureRestApi futurePostV1) throws HttpException, IOException {
		String userInfo = futurePostV1.future_userinfo();
		String userInfo4fix = futurePostV1.future_userinfo_4fix();
		OkCoinUserInfo okCoinUserInfo = new OkCoinUserInfo();
		System.out.println(userInfo);
		System.out.println(userInfo4fix);

		if (JSONObject.parseObject(userInfo).getLong("error_code") == 20022) {
			List<Contracts> cs = (List<Contracts>) net.sf.json.JSONArray.toList(net.sf.json.JSONObject.fromObject(userInfo4fix).getJSONObject("info").getJSONObject("btc").getJSONArray("contracts"), Contracts.class);
			Btc btc = new Btc();
			btc.setContracts(cs);
			btc.setBalance(net.sf.json.JSONObject.fromObject(userInfo4fix).getJSONObject("info").getJSONObject("btc").getDouble("balance"));
			btc.setRights(net.sf.json.JSONObject.fromObject(userInfo4fix).getJSONObject("info").getJSONObject("btc").getDouble("rights"));
			Info info = new Info();
			info.setBtc(btc);
			okCoinUserInfo.setInfo(info);
			okCoinUserInfo.setResult(net.sf.json.JSONObject.fromObject(userInfo4fix).getBoolean("result"));

		} else {
			List<Contracts> cs = (List<Contracts>) net.sf.json.JSONArray.toList(net.sf.json.JSONObject.fromObject(userInfo).getJSONObject("info").getJSONObject("btc").getJSONArray("contracts"), Contracts.class);
			Btc btc = new Btc();
			btc.setContracts(cs);
			btc.setBalance(net.sf.json.JSONObject.fromObject(userInfo).getJSONObject("info").getJSONObject("btc").getDouble("balance"));
			btc.setRights(net.sf.json.JSONObject.fromObject(userInfo).getJSONObject("info").getJSONObject("btc").getDouble("rights"));
			Info info = new Info();
			info.setBtc(btc);
			okCoinUserInfo.setInfo(info);
			okCoinUserInfo.setResult(net.sf.json.JSONObject.fromObject(userInfo).getBoolean("result"));
		}

		return okCoinUserInfo;
	}

	private static OkcoinOrder getOrder(IFutureRestApi futurePostV1) throws HttpException, IOException {
		String okCoinOrder = futurePostV1.future_order_info("btc_usd", "quarter", "-1", "1", "1", "50");
		System.out.println(okCoinOrder);
		List<Orders> os = (List<Orders>) net.sf.json.JSONArray.toList(net.sf.json.JSONObject.fromObject(okCoinOrder).getJSONArray("orders"), Orders.class);
		OkcoinOrder orders = new OkcoinOrder();
		orders.setOrders(os);
		orders.setResult(net.sf.json.JSONObject.fromObject(okCoinOrder).getBoolean("result"));
		return orders;
	}

	private static OkcoinOrder getOrder(IFutureRestApi futurePostV1, String orderId, String status, String currentPage, String pageLength) throws HttpException, IOException {
		String okCoinOrder = futurePostV1.future_order_info("btc_usd", "quarter", orderId, status, currentPage, pageLength);// "-1",
																															// "1",
																															// "1",
																															// "50");
		List<Orders> os = (List<Orders>) net.sf.json.JSONArray.toList(net.sf.json.JSONObject.fromObject(okCoinOrder).getJSONArray("orders"), Orders.class);
		OkcoinOrder orders = new OkcoinOrder();
		orders.setOrders(os);
		orders.setResult(net.sf.json.JSONObject.fromObject(okCoinOrder).getBoolean("result"));
		return orders;
	}

	public static ObjectMapper mapper = new ObjectMapper();

	public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
		return mapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
	}

	public static Date LongToDare(long str) throws ParseException {
		return new Date(str * 1000);
	}
}
